﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using Sun.Wadl;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace Hbrs.Soa.Restclient.Prototype
{
    class Program
    {
        static void Main(string[] args)
        {
            WADL2Code();
            Code2WADL();

            Console.WriteLine("Fertig");
            Console.ReadLine();
        }

        private static void Code2WADL()
        {
            Assembly asm = Assembly.LoadFrom(@"Testdata\RESTSingleton2.dll");
            foreach (Type asmtype in asm.GetTypes())
            {
                Type contractType = null;
                object[] attributes = asmtype.GetCustomAttributes(typeof(ServiceContractAttribute), true);
                if (attributes.Length == 0)
                {
                    Type[] interfaces = asmtype.GetInterfaces();
                    int i = 0;
                    while ((contractType == null) && i < interfaces.Length)
                    {
                        Type inf = interfaces[i];
                        attributes = inf.GetCustomAttributes(typeof(ServiceContractAttribute), true);
                        if (attributes.Length > 0)
                        {
                            contractType = inf;
                        }
                        i++;
                    }
                }

                bool serviceFound = (contractType != null);
                if (serviceFound)
                {
                    Console.WriteLine("ServiceContract gefunden:" + contractType.Name);

                    application app = new application();
                    app.doc = new doc[] { new doc() { title = "Auto-generated Service: " + contractType.Name } };

                    MethodInfo[] mis = contractType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                    var webinvokes =
                        from MethodInfo mi in mis
                        where mi.GetCustomAttributes(typeof(WebInvokeAttribute), true).Length > 0 ||
                              mi.GetCustomAttributes(typeof(WebGetAttribute), true).Length > 0
                        select mi;

                    app.Items = new object[webinvokes.Count()];
                    int i = 0;
                    foreach (MethodInfo info in webinvokes)
                    {
                        method m = new method();
                        m.id = info.Name;

                        WebGetAttribute wgAttr = (WebGetAttribute)info.GetCustomAttributes(typeof(WebGetAttribute), true).FirstOrDefault();
                        if (wgAttr != null)
                        {
                            m.name = "GET";
                        }
                        else
                        {
                            WebInvokeAttribute inAttr = (WebInvokeAttribute)info.GetCustomAttributes(typeof(WebInvokeAttribute), true).FirstOrDefault();
                            m.name = inAttr.Method;
                        }
                        app.Items[i] = m;
                        i++;
                    }

                    using (FileStream fs = File.Create(@"Testdata\RESTSingleton2.wadl"))
                    {
                        XmlSerializer xmlser = new XmlSerializer(typeof(application));
                        xmlser.Serialize(fs, app);
                        fs.Close();
                    }

                }
            }
        }

        private static void WADL2Code()
        {
            using (Stream fs = File.Open(@"Testdata\websearch.wadl", FileMode.Open))
            {
                XmlSerializer xmlser = new XmlSerializer(typeof(application));
                xmlser.UnknownNode += new XmlNodeEventHandler(xmlser_UnknownNode);
                application app = (application)xmlser.Deserialize(fs);

                CodeCompileUnit unit = new CodeCompileUnit();
                CodeNamespace ns = new CodeNamespace("Yahoo Search");
                unit.Namespaces.Add(ns);

                CodeTypeDeclaration type = new CodeTypeDeclaration("Resource");
                type.TypeAttributes = System.Reflection.TypeAttributes.Public;
                ns.Types.Add(type);

                foreach (object item in app.Items)
                {
                    if (item is method)
                    {
                        method m = (method)item;

                        CodeTypeDeclaration respType = new CodeTypeDeclaration("RequestType" + m.name.TrimStart());
                        ns.Types.Add(respType);

                        foreach (param par in m.request.param)
                        {
                            CodeMemberProperty prop = new CodeMemberProperty();
                            prop.Name = par.name;
                            prop.HasGet = true;
                            prop.HasSet = true;
                            prop.Attributes = MemberAttributes.Public;
                            switch (par.type.Name)
                            {
                                case "string":
                                    prop.Type = new CodeTypeReference(typeof(string));
                                    break;
                                case "int":
                                    prop.Type = new CodeTypeReference(typeof(int));
                                    break;
                                default:
                                    prop.Type = new CodeTypeReference(typeof(object));
                                    break;
                            }
                            respType.Members.Add(prop);
                        }
                    }
                }

                CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
                using (TextWriter tw = File.CreateText(@"Testdata\websearch." + provider.FileExtension))
                {
                    provider.GenerateCodeFromCompileUnit(unit, tw, null);
                }
            }
        }

        static void xmlser_UnknownNode(object sender, XmlNodeEventArgs e)
        {
            Console.WriteLine("Fehler in XML-Dokument." + e.Name);
        }
    }
}
